package com.lry.basic.nio.mapped;

import lombok.extern.slf4j.Slf4j;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class MappedFile<T> {


    private AtomicInteger writePos = new AtomicInteger(0);

    private MappedByteBuffer mappedByteBuffer;

    private IndexFile<T> indexFile;

    private String url;

    private long size;

    private static String default_url = "d://1.txt";

    private static long default_size = 1024*1024;

    public MappedFile(IndexFile indexFile){
        this(indexFile,default_url,default_size);
    }

    public MappedFile(IndexFile indexFile,String url){
        this(indexFile,url,default_size);
    }

    public MappedFile(IndexFile indexFile,long size){
        this(indexFile,default_url,size);
    }

    public MappedFile(IndexFile indexFile,String url,long size){
        assert null!=indexFile;
        assert null!=url&&url.length()>0;
        assert size>0;
        this.indexFile = indexFile;
        this.url = url;
        this.size = size;
        this.mappedByteBuffer = getMappedByteBuffer();
    }


    private MappedByteBuffer getMappedByteBuffer(){
        //指定内存映射文件的大小
        //只读，读写（写是及时写到磁盘，不需要flush），private（写时复制）
        try {
            mappedByteBuffer = new RandomAccessFile(url,"rw").
                    getChannel().
                    map(FileChannel.MapMode.READ_WRITE,0,size);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //初始化写指针和读索引
        writePos.set(indexFile.calWritePos(mappedByteBuffer.slice()));

        return mappedByteBuffer;
    }




    public void put(T frame){
        assert null != frame;
        byte[] bytes = indexFile.toBytes(frame,writePos.get());
        if(null==bytes||bytes.length==0)
            return;
        //copy一份
        ByteBuffer buf = mappedByteBuffer.slice();
        //追加文件
        buf.position(writePos.get());
        buf.put(bytes);
        //写指针偏移
        writePos.addAndGet(bytes.length);
    }


    public T findById(int id){
        return indexFile.get(id,mappedByteBuffer.slice());
    }






}
